home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / bin / mkpasswd < prev    next >
Text File  |  1995-07-21  |  5KB  |  201 lines

  1. #!/usr/skunk/bin/expect --
  2. # mkpasswd - make a password, if username given, set it.
  3. # Author: Don Libes, NIST
  4.  
  5. # defaults
  6. set length 9
  7. set minnum 2
  8. set minlower 2
  9. set minupper 2
  10. set verbose 0
  11. set distribute 0
  12.  
  13. if [file executable /bin/yppasswd] {
  14.     set defaultprog /bin/yppasswd
  15. } else {
  16.     set defaultprog /bin/passwd
  17. }
  18. set prog $defaultprog
  19.  
  20. while {[llength $argv]>0} {
  21.     set flag [lindex $argv 0]
  22.     switch -- $flag \
  23.     "-l" {
  24.         set length [lindex $argv 1]
  25.         set argv [lrange $argv 2 end]
  26.     } "-d" {
  27.         set minnum [lindex $argv 1]
  28.         set argv [lrange $argv 2 end]
  29.     } "-c" {
  30.         set minlower [lindex $argv 1]
  31.         set argv [lrange $argv 2 end]
  32.     } "-C" {
  33.         set minupper [lindex $argv 1]
  34.         set argv [lrange $argv 2 end]
  35.     } "-v" {
  36.         set verbose 1
  37.         set argv [lrange $argv 1 end]
  38.     } "-p" {
  39.         set prog [lindex $argv 1]
  40.         set argv [lrange $argv 2 end]
  41.     } "-2" {
  42.         set distribute 1
  43.         set argv [lrange $argv 1 end]
  44.     } default {
  45.         set user [lindex $argv 0]
  46.         set argv [lrange $argv 1 end]
  47.         break
  48.     }
  49. }
  50.  
  51. if {[llength $argv]} {
  52.     puts "usage: mkpasswd \[args] \[user]"
  53.     puts "  where arguments are:"
  54.     puts "    -l #      (length of password, default = $length)"
  55.     puts "    -d #      (min # of digits, default = $minnum)"
  56.     puts "    -c #      (min # of lowercase chars, default = $minlower)"
  57.     puts "    -C #      (min # of uppercase chars, default = $minupper)"
  58.     puts "    -v        (verbose, show passwd interaction)"
  59.     puts "    -p prog   (program to set password, default = $defaultprog)"
  60.     exit 1
  61. }
  62.  
  63. if {$minnum + $minlower + $minupper > $length} {
  64.     puts "impossible to generate $length-character password\
  65.         with $minnum numbers, $minlower lowercase letters,\
  66.         and $minupper uppercase letters"
  67.     exit 1
  68. }
  69.  
  70. # if there is any underspecification, use additional lowercase letters
  71. set minlower [expr $length - ($minnum + $minupper)]
  72.  
  73. set lpass ""        ;# password chars typed by left hand
  74. set rpass ""        ;# password chars typed by right hand
  75.  
  76. # insert char into password at a random position
  77. proc insert {pvar char} {
  78.     upvar $pvar p
  79.  
  80.     set p [linsert $p [rand [expr 1+[llength $p]]] $char]
  81. }
  82.  
  83. set _ran [pid]
  84.  
  85. proc rand {m} {
  86.     global _ran
  87.  
  88.     set period 233280
  89.     set _ran [expr ($_ran*9301 + 49297) % $period]
  90.     expr int($m*($_ran/double($period)))
  91. }
  92.  
  93. # choose left or right starting hand
  94. set initially_left [set isleft [rand 2]]
  95.  
  96. # given a size, distribute between left and right hands
  97. # taking into account where we left off
  98. proc psplit {max lvar rvar} {
  99.     upvar $lvar left $rvar right
  100.     global isleft
  101.  
  102.     if {$isleft} {
  103.         set right [expr $max/2]
  104.         set left [expr $max-$right]
  105.         set isleft [expr !($max%2)]
  106.     } else {
  107.         set left [expr $max/2]
  108.         set right [expr $max-$left]
  109.         set isleft [expr $max%2]
  110.     }
  111. }
  112.  
  113. if {$distribute} {
  114.     set lkeys {q w e r t a s d f g z x c v b}
  115.     set rkeys {y u i o p h j k l n m}
  116.     set lnums {1 2 3 4 5 6}
  117.     set rnums {7 8 9 0}
  118. } else {
  119.     set lkeys {a b c d e f g h i j k l m n o p q r s t u v w x y z}
  120.     set rkeys {a b c d e f g h i j k l m n o p q r s t u v w x y z}
  121.     set lnums {0 1 2 3 4 5 6 7 8 9}
  122.     set rnums {0 1 2 3 4 5 6 7 8 9}
  123. }
  124.  
  125. set lkeys_length [llength $lkeys]
  126. set rkeys_length [llength $rkeys]
  127. set lnums_length [llength $lnums]
  128. set rnums_length [llength $rnums]
  129.  
  130. psplit $minnum left right
  131. for {set i 0} {$i<$left} {incr i} {
  132.     insert lpass [lindex $lnums [rand $lnums_length]]
  133. }
  134. for {set i 0} {$i<$right} {incr i} {
  135.     insert rpass [lindex $rnums [rand $rnums_length]]
  136. }
  137.  
  138. psplit $minlower left right
  139. for {set i 0} {$i<$left} {incr i} {
  140.     insert lpass [lindex $lkeys [rand $lkeys_length]]
  141. }
  142. for {set i 0} {$i<$right} {incr i} {
  143.     insert rpass [lindex $rkeys [rand $rkeys_length]]
  144. }
  145.  
  146. psplit $minupper left right
  147. for {set i 0} {$i<$left} {incr i} {
  148.     insert lpass [string toupper [lindex $lkeys [rand $lkeys_length]]]
  149. }
  150. for {set i 0} {$i<$right} {incr i} {
  151.     insert rpass [string toupper [lindex $rkeys [rand $rkeys_length]]]
  152. }
  153.  
  154. # merge results together
  155. if {$initially_left} {
  156.     regexp "(\[^ ]*) *(.*)" "$lpass" x password lpass
  157.     while {[llength $lpass]} {
  158.         regexp "(\[^ ]*) *(.*)" "$password$rpass" x password rpass
  159.         regexp "(\[^ ]*) *(.*)" "$password$lpass" x password lpass
  160.     }
  161.     if {[llength $rpass]} {
  162.         append password $rpass
  163.     }        
  164. } else {
  165.     regexp "(\[^ ]*) *(.*)" "$rpass" x password rpass
  166.     while {[llength $rpass]} {
  167.         regexp "(\[^ ]*) *(.*)" "$password$lpass" x password lpass
  168.         regexp "(\[^ ]*) *(.*)" "$password$rpass" x password rpass
  169.     }
  170.     if {[llength $lpass]} {
  171.         append password $lpass
  172.     }        
  173. }
  174.  
  175. if {[info exists user]} {
  176.     if {!$verbose} {
  177.         log_user 0
  178.     }
  179.  
  180.     spawn $prog $user
  181.     expect {
  182.         "assword:" {
  183.             send "$password\r"
  184.             exp_continue
  185.         }
  186.     }
  187.  
  188.     # if user isn't watching, check status
  189.     if {!$verbose} {
  190.         if {[lindex [wait] 3]} {
  191.             puts -nonewline "$expect_out(buffer)"
  192.             exit 1
  193.         }
  194.     }
  195. }
  196.  
  197. if {$verbose} {
  198.     puts -nonewline "password for $user is "
  199. }
  200. puts "$password"
  201.